#include "PageCache.h"

PageCache PageCache::_inst;

PageCache& PageCache::getInstance()
{
    return _inst;
}

Span *PageCache::newSpan(size_t nPage)
{
    // 如果当前pageCache里面有需要的页数的span，就直接返回
    if(!_pageSpanList[nPage].empty()){
        return _pageSpanList[nPage].pop();
    }

    // 没有刚好符合大小的span，所以遍历比他大的，将大的span切分为 k 和 span->_n - k 大小的两个span
    size_t k = nPage + 1;
    while(k <= NPAGES - 1){
        if(!_pageSpanList[k].empty()){
           Span *nSpan = _pageSpanList[k].pop();
           Span *kSpan = new Span;

           kSpan->_page_id = nSpan->_page_id;
           nSpan->_page_id += nPage;

           kSpan->_n = nPage;
           nSpan->_n -= nPage; 

           // 将切分后的span挂载到符合的大小上，需要的span返回
           _pageSpanList[nSpan->_n].pushFront(nSpan);

           // 将且分出的kSpan所有页，添加到映射中
           for(size_t k = 0; k < kSpan->_n; k++){
            _pageIdSpanMap[kSpan->_page_id + k] = kSpan;
           }

           return kSpan;
        }
        k++;
    }

    // 如果最大的 128 页的span也没有，那么就到堆中去申请
    void *ptr = systemAlloc(NPAGES - 1);
    
    Span *bigSpan = new Span;
    bigSpan->_n = NPAGES - 1;
    bigSpan->_page_id = (PAGE_ID)ptr >> PAGE_SHIFT;
    _pageSpanList[NPAGES - 1].pushFront(bigSpan);

    return newSpan(nPage);
}

mutex &PageCache::getMtx()
{
    return _mtx;
}

Span *PageCache::pageIdSpanMap(void *obj)
{
    PAGE_ID pageId = (PAGE_ID)obj >> PAGE_SHIFT;
    unordered_map<PAGE_ID, Span *>::iterator iter = _pageIdSpanMap.find(pageId);
    
    if(iter != _pageIdSpanMap.end()){
        return iter->second;
    }else{
        assert(false);
        return nullptr;
    }

}

void PageCache::dealloc(Span *span)
{
    
}